/**
 * 
 */
package com.wolfpire.system.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.wolfpire.system.common.Constants;
import com.wolfpire.system.common.EasyuiPage;
import com.wolfpire.system.common.EasyuiPagination;
import com.wolfpire.system.common.JsonHelper;
import com.wolfpire.system.common.Page;
import com.wolfpire.system.common.Result;
import com.wolfpire.system.model.Attachment;
import com.wolfpire.system.service.AttachmentService;

/**
 * 附件控制器
 * @author lihd
 *
 */

@Controller
@RequestMapping("/attachment")
public class AttachmentController {
	
	private static final Pattern extPattern = Pattern.compile("doc|docx|xls|xlsx|txt|jpg|gif|png|rar|zip|tif|pdf|apk|ppt|pptx|pdm|apk|sql");
	private static final String POINT = ".";
	
	@Resource AttachmentService attachmentService;
	
	@ResponseBody
	@RequestMapping("/attachments")
	public List<Attachment> attachments(Long bizId, String attaType) {
		if (null != bizId) {
			return this.attachmentService.getByBiz(bizId, attaType);
		}
		return null;
	}
	
	@ResponseBody
	@RequestMapping("/upload")
	public String upload(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "moudle", required = false) String moudle,
			@RequestParam(value = "title", required = false) String title) {
		try {
//			String rootPath = request.getSession().getServletContext().getRealPath("/");
			//rootPath = rootPath + ".." + File.separator;
			String rootPath = Constants.FILE_ROOT_PATH;
			if (!StringUtils.isBlank(moudle)) {
				moudle = "atta";
			}
			// 返回数据
			Attachment att = new Attachment();
		
			if (ServletFileUpload.isMultipartContent(request)) {
				DiskFileItemFactory factory = new DiskFileItemFactory();//磁盘对象
				ServletFileUpload upload = new ServletFileUpload(factory);
				List<FileItem> items = upload.parseRequest(request);

				// 获取存储路径
				String tempPath =  moudle + File.separator + new SimpleDateFormat("yyyyMMdd").format(new Date());
				String savePath = rootPath + File.separator + "upload" + File.separator + tempPath;
				File saveDir = new File(savePath);
				if (!saveDir.exists()) {
					saveDir.mkdirs();
				}
				Iterator<FileItem> itr = items.iterator();
				String newFileName = null;
				while (itr.hasNext()) {
					FileItem item = itr.next();
					if ((!item.isFormField()) && (item.getName().length() > 0)) {
						String extName = FilenameUtils.getExtension(item.getName()).toLowerCase(Locale.ENGLISH);
						//扩展名判断
						if(extPattern.matcher(extName).find()){
							newFileName = System.currentTimeMillis() + POINT + extName;
							att.setFilePath("upload" + File.separator + tempPath + File.separator + newFileName);
							att.setFileName(item.getName());
							att.setFileSize(String.valueOf(item.getSize()));
							att.setTitle((null != title) ? title : StringUtils.EMPTY);
							this.attachmentService.save(att);
							String filePath = savePath + File.separator + newFileName;
							File file = new File(filePath);
							item.write(file);
						}else{
//							response.getWriter().print("{error:'上传文件格式不符合要求！'}");
//							return new Result(false, "上传文件格式不符合要求！");
							return "{error:'上传文件格式不符合要求！'}";
						}
					}
				}
//				response.getWriter().print(JsonHelper.getJsonString(att));
			}
			return JsonHelper.getJsonString(att);
		} catch (Exception e) {
			e.printStackTrace();
//			response.getWriter().print("{error:'未知异常！请检查文件大小、格式是否符合要求！'}");
//			return new Result(false, "上传文件格式不符合要求！");
			return "{error:'未知异常！请检查文件大小、格式是否符合要求！'}";
		}
	}
	
	@RequestMapping("/down")
	public String down(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "attId", required = false) Long attId, ModelMap map) {
		try {
			OutputStream out = null; 
			if(null != attId){
				Attachment attachment = this.attachmentService.get(attId);
//				String rootPath = request.getSession().getServletContext().getRealPath("/");
				//rootPath = "D:\\workflow-new" + File.separator;
				String rootPath = Constants.FILE_ROOT_PATH + File.separator;
				String allPath = rootPath + attachment.getFilePath();
				System.out.println("allPath============================"+allPath);
				// path是指欲下载的文件的路径。
				File file = new File(allPath);
//				String filename = file.getName();
//				String ext = filename.substring(filename.lastIndexOf(POINT) + 1);// .toUpperCase();
				String newfilename = attachment.getFileName();
//				String realName = attachment.getFileName();
//				realName = realName.substring(realName.lastIndexOf(POINT) + 1);
//				if (realName != null && !"".equals(realName))
//					newfilename = realName + POINT + ext;
				InputStream fis = new BufferedInputStream(new FileInputStream(allPath));
				byte[] buffer = new byte[fis.available()];
				fis.read(buffer);
				fis.close();
				// 清空response
				response.reset();
				// 设置response的Header
				response.addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(newfilename, "UTF-8"));
				response.addHeader("Content-Length", "" + file.length());
				out = new BufferedOutputStream(response.getOutputStream());
				response.setContentType("application/octet-stream");
				out.write(buffer);
				out.flush();
				out.close();
				out = null;
			}
		} catch(Exception e){
			e.printStackTrace();
			System.out.println("---------文件下载失败，该文件不存在。-----------");
			map.put("message", "文件下载失败，该文件不存在。");
			return "common/message";
		}
		
		return null;
	}
	
	@ResponseBody
	@RequestMapping(value = "/delete", method = {RequestMethod.GET, RequestMethod.POST})
	public Result delete(HttpServletRequest request,
			@RequestParam(value = "filePath", required = false) String filePath,
			@RequestParam(value = "attId", required = false) Long attId) {
		try {
			/*// 取工程根目录下
			String rootPath = request.getSession().getServletContext().getRealPath("/");*/
			if (StringUtils.isBlank(filePath) && null == attId) {
				return new Result(true);
			}
			if (null != attId) {
				Attachment atta = this.attachmentService.get(attId);
				filePath = atta.getFilePath();
				this.attachmentService.del(attId);
			}
			if (!StringUtils.isBlank(filePath)) {
				String rootPath = Constants.FILE_ROOT_PATH + File.separator;
				String allPath = rootPath+ filePath;
				File file = new File(allPath);
				if (file.exists()) {
					file.delete();
				}
			}
			return new Result(true);
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false);
		}
	}
	
	@ResponseBody
	@RequestMapping("/queryByPiId")
	public EasyuiPagination<Map<String, Object>> queryByPiId(
			EasyuiPage<Map<String, Object>> page,
			@RequestParam(value = "projectIndexId", required = false) Long projectIndexId,
			Attachment filterAttachment) {
		Page<Map<String, Object>> attachments = this.attachmentService.setAttachmentsByPiId(page, projectIndexId, filterAttachment);
		return new EasyuiPagination<Map<String, Object>>(attachments);
	}
	
	@RequestMapping(value = "/downs", method = {RequestMethod.GET, RequestMethod.POST})
	public String downs(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "attIdsStr", required = false) String attIdsStr,
			@RequestParam(value = "pkgName", required = false) String projectIndexName,
			ModelMap map) {
		// TODO:
		try {
			if (StringUtils.isBlank(attIdsStr)) {
				System.out.println("---------恶意访问批量下载，居心裹测哦。-----------");
				map.put("message", "恶意访问批量下载，居心裹测哦。");
				return "common/message";
			}
			if (!StringUtils.isBlank(projectIndexName)) {
				System.out.println(projectIndexName);
			}
			String[] attIdsArr = attIdsStr.split(",");
			Long[] attIds = new Long[attIdsArr.length];
			for (String str : attIdsArr) {
				attIds = ArrayUtils.add(attIds, Long.parseLong(str));
			}
			List<File> files = new ArrayList<File>();
			String rootPath = Constants.FILE_ROOT_PATH + File.separator;
			List<Attachment> attachments = this.attachmentService.getById(attIds);
			for (Attachment atta : attachments) {
				String allPath = rootPath + atta.getFilePath();
				System.out.println("allPath============================"+allPath);
				File file = new File(allPath);
				files.add(file);
			}
			String zipFileName = System.currentTimeMillis() + ".zip"; 
					//UUID.randomUUID().toString() + ".zip";
			String outFilePath = rootPath + "/temp/";
		    createFile(outFilePath, zipFileName);
		    File file = new File(outFilePath + zipFileName);
		    //文件输出流
		    FileOutputStream outStream = new FileOutputStream(file);
		    //压缩流
		    ZipOutputStream out = new ZipOutputStream(outStream);
//		    toClient.setEncoding("gbk");
		    zipFile(files, out);
		    out.close();
		    outStream.close();
		    this.downloadFile(file, response,true);
			
		} catch(Exception e){
			e.printStackTrace();
			System.out.println("---------文件下载失败，该文件不存在。-----------");
			map.put("message", "文件下载失败，该文件不存在。");
			return "common/message";
		}
		
		return null;
	}
	
	// 创建文件
	public void createFile(String path, String fileName) {
		File file = new File(path);
		if (!file.exists()) {
			file.mkdirs();
		}
		file = new File(file, fileName);
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				System.out.println("=================文件创建失败=================");
				e.printStackTrace();
			}
		}
	}
	
	public static void zipFile(List<File> files, ZipOutputStream out) throws IOException {
		for (File file : files) {
			zipFile(file, out);
		}
	}
	
	public static void zipFile(File file, ZipOutputStream out) throws IOException {
		
		if (file.exists()) {
			if (file.isFile()) {
				FileInputStream in = new FileInputStream(file);
				BufferedInputStream bin = new BufferedInputStream(in);
				ZipEntry entry = new ZipEntry(file.getName());
				out.putNextEntry(entry);
				final int MAX_BYTE = 10 * 1024 * 1024;
				long streamTotal = 0L;
				int streamNum = 0;
				int leaveByte = 0;
				byte[] inOutByte;
				streamTotal = bin.available();
				streamNum = (int) Math.floor(streamTotal / MAX_BYTE);
				leaveByte = (int) (streamTotal % MAX_BYTE);
				if (streamNum > 0) {
					for (int i = 0; i < streamNum; i++) {
						inOutByte = new byte[MAX_BYTE];
						bin.read(inOutByte, 0, MAX_BYTE);
						out.write(inOutByte, 0, MAX_BYTE);
					}
				}
				inOutByte = new byte[leaveByte];
				bin.read(inOutByte, 0, leaveByte);
				out.write(inOutByte);
				out.closeEntry();
				bin.close(); // 关闭
				in.close();
			} else {
				throw new FileNotFoundException("文件不存在！");
			}
		}
	}
	
	public void downloadFile(File file, HttpServletResponse response, boolean isDelete) {
        try {
            // 以流的形式下载文件。
            BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            OutputStream out = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes("UTF-8"),"ISO-8859-1"));
            out.write(buffer);
            out.flush();
            out.close();
            if(isDelete) {
            	file.delete();        //是否将生成的服务器端文件删除
            }
         } 
         catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
